package cn.wj.school.cloud.freemarker;

import freemarker.template.TemplateModelException;
import freemarker.template.TemplateTransformModel;

import java.io.IOException;
import java.io.Writer;
import java.util.Map;

public class JsonStringEscape implements TemplateTransformModel {

  private static final char[] QUOT = "\\\"".toCharArray();

  private static final char[] APOS = "\\\'".toCharArray();

  @Override
  public Writer getWriter(Writer out, Map args) throws TemplateModelException, IOException {
    return new JsonStringWriter(out);
  }

  private class JsonStringWriter extends Writer {

    private final Writer out;

    JsonStringWriter(Writer out) {
      this.out = out;
    }

    @Override
    public void write(int c) throws IOException {
      switch (c) {
      case 34:
        this.out.write(JsonStringEscape.QUOT, 0, 2);
        break;
      case 39:
        this.out.write(JsonStringEscape.APOS, 0, 2);
        break;
      default:
        this.out.write(c);
      }
    }

    @Override
    public void write(char[] cbuf, int off, int len) throws IOException {
      int lastoff = off;
      int lastpos = off + len;
      for (int i = off; i < lastpos; i++) {
        switch (cbuf[i]) {
        case '"':
          this.out.write(cbuf, lastoff, i - lastoff);
          this.out.write(JsonStringEscape.QUOT, 0, 2);
          lastoff = i + 1;
          break;
        case '\'':
          this.out.write(cbuf, lastoff, i - lastoff);
          this.out.write(JsonStringEscape.APOS, 0, 2);
          lastoff = i + 1;
          break;
        default:
          break;
        }
      }
      int remaining = lastpos - lastoff;
      if (remaining > 0) {
        this.out.write(cbuf, lastoff, remaining);
      }

    }

    @Override
    public void flush() throws IOException {
      this.out.flush();

    }

    @Override
    public void close() throws IOException {
      // Do nothing
    }
  }

}
